package me.yangbajing.web
package snippet

import scala.xml.NodeSeq

import net.liftweb.util.Helpers._
import net.liftweb.http.{SHtml, S, DispatchSnippet}
import net.liftweb.util.{PassThru, ClearNodes, CssSel}
import net.liftweb.common.{Failure, Full}
import net.liftweb.http.js.{JE, JsCmds, JsCmd}

import me.yangbajing.model.{ReqUser, Account, MUser}
import yangbajing.util.MarkdownHelpers
import yangbajing.util.Imports.Y

object UserSnippet extends DispatchSnippet {
  def dispatch = {
    case "info" => info
    case "datas" => datas
    case "detail" => detail
    case "changePassword" => changePassword
  }

  def info(nodeSeq: NodeSeq): NodeSeq = {
    val cssSel =
      for {
        userId <- S.attr("account") or W.reqDocument.is.map(_.creator) or W.theAccount.is.map(_.id)
        user <- MUser.findOne(userId)
      } yield _info(user)

    cssSel map (_ apply nodeSeq) openOr <strong class="text-danger">没有有效用户</strong>
  }

  private def _info(user: MUser): CssSel = {
    val accountSel =
      W.theAccount.is match {
        case Full(account) => "#user-account" #> PassThru
        case _ => "#user-account" #> ClearNodes
      }

    ".avatar" #> (
      "a [href]" #> W.hrefUser(user.id) &
        "img [src]" #> MUser.avatarUri(user.id)
      ) &
      ".avatar-account *" #> user.nickOrId &
      ".avatar-signature *" #> user.signature.getOrElse("") &
      ".avatar-contact *" #> user.contact.map(MarkdownHelpers.parseToNodeSeq).getOrElse(NodeSeq.Empty) &
      accountSel
  }

  def datas(nodeSeq: NodeSeq): NodeSeq = {
    val cssSel =
      "#dd" #> ""

    cssSel(nodeSeq)
  }

  def detail(nodeSeq: NodeSeq): NodeSeq = {
    val cssSel =
      for {
        account <- W.theAccount.is
      } yield _detail(account)

    cssSel map (_ apply nodeSeq) openOr <h1 class="text-danger">账号会话不存在</h1>
  }

  private def _detail(account: Account): CssSel = {
    val reqUser = ReqUser(account.user)

    "#control-user-id :text [value]" #> account.id &
      "#control-user-email :text [value]" #> account.user.email &
      "@nick" #> SHtml.text(reqUser.nick.getOrElse(""), v => reqUser.nick = Y.option(v)) &
      "@signature" #> SHtml.textarea(reqUser.signature.getOrElse(""), v => reqUser.signature = Y.option(v)) &
      "@contact" #> SHtml.textarea(reqUser.contact.getOrElse(""), v => reqUser.contact = Y.option(v)) &
      "@submit" #> SHtml.hidden(() =>
        MUser.modify(account.id, reqUser) match {
          case Full(user) =>
            W.saveSessionAndCookie(user, true)
            JsCmds.Alert("编辑人个信息成功") & JsCmds.Reload

          case Failure(msg, _, _) =>
            JE.Call("formControlError", "#control-user-submit", "编辑个人信息失败: " + msg).cmd

          case _ =>
            JE.Call("formControlError", "#control-user-submit", "编辑个人信息失败").cmd
        })
  }

  def changePassword(nodeSeq: NodeSeq): NodeSeq = {
    val cssSel =
      for {
        account <- W.theAccount.is
      } yield _changePassowrd(account)

    cssSel map (_ apply nodeSeq) openOr <h1 class="text-danger">用户会话不存在</h1>
  }

  private def _changePassowrd(account: Account): CssSel = {
    var oldPassowrd = ""
    var newPassword = ""
    var repeatPassword = ""

    def funcSubmit(): JsCmd =
      if (newPassword != repeatPassword)
        JE.Call("formControlError", "#control-submit", "两次密码不匹配").cmd
      else
        MUser.modifyPassword(account.id, oldPassowrd, repeatPassword) match {
          case Full(1) =>
            W.theAccount.remove()
            JsCmds.Alert("修改密码成功，请重新登录。") & JsCmds.RedirectTo("/h/user/sign_in")

          case Failure(msg, _, _) =>
            JE.Call("formControlError", "#control-submit", "修改密码失败：" + msg).cmd

          case _ =>
            JE.Call("formControlError", "#control-submit", "修改密码失败").cmd
        }

    "@old-password" #> SHtml.password(oldPassowrd, oldPassowrd = _) &
      "@new-password" #> SHtml.password(newPassword, newPassword = _) &
      "@repeat-password" #> SHtml.password(repeatPassword, repeatPassword = _) &
      "@submit" #> SHtml.hidden(funcSubmit)
  }

}
